package mate.dart;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import mate.dart.gui.DartBoardPanel;
import mate.dart.gui.GameCricetScoreBoard;
import mate.dart.gui.GameKillerScoreBoard;
import mate.dart.gui.GameX01ScoreBoard;
import mate.dart.utils.Configuration;

public class JDartScorer extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	private DartBoardPanel boardPanel;
	private JPanel gameCardPanel;	
	
	private AbstractGame[] games = new AbstractGame[4];
	
	private DartBoardSubject subject;
	
	private int curentGame;
	
	public JDartScorer() {
		initComponents();
		initMenuBar();
		
		AbstractGame g = games[curentGame];
		subject = new DartBoardSubject();
		subject.addListener(g, g.getName());
		boardPanel.setBoardSubject(subject);
		pack();
	}

	private void initComponents() {
		setLayout(new BorderLayout());
		boardPanel = new DartBoardPanel();
		add(boardPanel, BorderLayout.WEST);

		gameCardPanel = new JPanel(new CardLayout());

		Box box = Box.createHorizontalBox();
		box.add(Box.createHorizontalStrut(5));
		box.add(gameCardPanel);
		add(box, BorderLayout.CENTER);

		initGames(2);
		for (AbstractGame game : games) {
			gameCardPanel.add(game.getName(), game);
		}
		((CardLayout) gameCardPanel.getLayout()).show(gameCardPanel, 
				games[curentGame].getName());
		
	}
	
	private void initGames(int players) {
		games[0] = new GameX01ScoreBoard(301);
		games[1] = new GameX01ScoreBoard(501);
		games[2] = new GameCricetScoreBoard();
		games[3] = new GameKillerScoreBoard();
		
		for (AbstractGame game : games) {
			game.setPlayers(players);
		}
		curentGame = 0; //which game shoud be shown on the start
	}

	public void actionPerformed(ActionEvent e) {
		
		if ("Preferences".equals(e.getActionCommand())) {
			String response = JOptionPane.showInputDialog(getRootPane(), "Players ?");
			try {
				int p = Integer.parseInt(response);
				if (p < 0 || p > 10) return;
				for (AbstractGame game : games) {
					game.setPlayers(p);
				}
			} catch (NumberFormatException nfe) {
				//do not nothing just return
				return;
			}
			pack();
			return;
		}
		
		if (Configuration.warnOnChangingGame()) {
			if (JOptionPane.CANCEL_OPTION == JOptionPane.showConfirmDialog(
					getRootPane(), "Current game will be lost. Continue ?",
					"Are you sure", JOptionPane.OK_CANCEL_OPTION)) {
				
				return;
			}
		}
		
		if ("New".equals(e.getActionCommand())) {
			games[curentGame].clear();
			return;
		}
		
		String newGameName = e.getActionCommand();
		String currentGameName = games[curentGame].getName();
		
		if (newGameName.equals(currentGameName)) return;
		
		subject.removeListener(currentGameName);
		curentGame = getGameIndex(newGameName);  
		games[curentGame].clear();
		subject.addListener(games[curentGame], newGameName);
		((CardLayout) gameCardPanel.getLayout()).show(gameCardPanel, newGameName);
	}

	private void initMenuBar() {
		JMenuBar menuBar;
		JMenu menu;
		JMenuItem menuItem;

		menuBar = new JMenuBar();

		menu = new JMenu("Game");
		menu.getAccessibleContext().setAccessibleDescription("Choose the game");
		menu.setMnemonic(KeyEvent.VK_G);
		menuBar.add(menu);

        menuItem = new JMenuItem("New", KeyEvent.VK_N);
        menuItem.addActionListener(this);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(                                                              
                KeyEvent.VK_N, ActionEvent.CTRL_MASK)); 		
        menu.add(menuItem);
        menu.addSeparator();
        
		for (AbstractGame game : games) {
	        menuItem = new JMenuItem(game.getName());
	        menuItem.setMnemonic(game.getName().getBytes()[0]);
	        menuItem.addActionListener(this);
			menu.add(menuItem);
		}
		menu.addSeparator();
        menuItem = new JMenuItem("Preferences", KeyEvent.VK_P);
        menuItem.addActionListener(this);
		menu.add(menuItem);
		
		menu = new JMenu("Help");
		menu.getAccessibleContext().setAccessibleDescription("Help");
		menu.setMnemonic(KeyEvent.VK_H);
		menu.setEnabled(false);
		menuBar.add(menu);

		menuItem = new JMenuItem("How to play", KeyEvent.VK_P);
        menuItem.addActionListener(this);
        menu.add(menuItem);
		
		menuItem = new JMenuItem("About", KeyEvent.VK_A);
        menuItem.addActionListener(this);
        menu.add(menuItem);
        
		setJMenuBar(menuBar);
	}
	
	private int getGameIndex(String name) {
		for (int i = 0; i < games.length; i++) {
			if (games[i].getName().equals(name)) {
				return i;
			}
		}
		throw new IllegalArgumentException ("Cannot find a game for name: "  + name  + ".");
	}

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				final JDartScorer lvqViewer = new JDartScorer();
				lvqViewer.setTitle("Java Dart Scorer");
				lvqViewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				lvqViewer.setVisible(true);
			}
		});

	}

}
